package com.fmy.springbootutils.util;

import com.fmy.springbootutils.unusual.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 日期转换类
 * </p>
 *
 * @author: fmy
 * 2018/4/25 17:11
 */
@Slf4j
public class DateUtil {

    public static final String YMD = "yyyy-MM-dd";
    public static final String YMD_HMS = "yyyy-MM-dd HH:mm:ss";

    /**
     * 日期格式转换成字符串
     *
     * @param pattern 转换类型
     * @param date
     * @return
     */
    public static String dateToString(String pattern, Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(date);
    }

    /**
     * 字符串转日期
     *
     * @param pattern 转换类似
     * @param str
     * @return
     * @throws ParseException
     */
    public static Date stringToDate(String pattern, String str) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        try {
            return simpleDateFormat.parse(str);
        } catch (ParseException e) {
            throw new BusinessException(e.getMessage());
        }
    }

    /**
     * 计算两个日期之间相隔的日期
     *
     * @param startTime 日期格式请转换为yyyy-MM-dd
     * @param endTime   日期格式请转换为yyyy-MM-dd
     * @return
     */
    public static List<Object> calculationDay(Date startTime, Date endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<Object> objs = new ArrayList<>();
        objs.add(sdf.format(startTime));//记录开始日期
        Calendar c = Calendar.getInstance();
        c.setTime(startTime);
        while (c.getTime().getTime() < endTime.getTime()) {
            //如果当前追加日期还小于最后日期的话继续循环
            c.add(Calendar.DAY_OF_MONTH, 1);// 与开始日期加1
            objs.add(sdf.format(c.getTime()));
        }
        return objs;
    }

    /**
     * 计算两个日期之间相隔的月份
     *
     * @param startTime 日期格式
     * @param endTime   日期格式
     * @return
     */
    public static List<Object> calculationMonth(Date startTime, Date endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        List<Object> objs = new ArrayList<>();
        objs.add(sdf.format(startTime));//记录开始日期
        Calendar c = Calendar.getInstance();
        c.setTime(startTime);
        while (c.getTime().getTime() < endTime.getTime()) {
            //如果当前追加日期还小于最后日期的话继续循环
            c.add(Calendar.MONTH, 1);// 与开始日期加1
            objs.add(sdf.format(c.getTime()));
        }
        return objs;
    }

    /**
     * 计算两个年份相隔的年份
     *
     * @param startTime 日期格式请转换为yyyy
     * @param endTime   日期格式请转换为yyyy
     * @return
     */
    public static List<Object> calculationYear(Date startTime, Date endTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        List<Object> objs = new ArrayList<>();
        objs.add(sdf.format(startTime));//记录开始日期
        Calendar c = Calendar.getInstance();
        c.setTime(startTime);
        while (c.getTime().getTime() < endTime.getTime()) {
            //如果当前追加日期还小于最后日期的话继续循环
            c.add(Calendar.YEAR, 1);// 与开始日期加1
            objs.add(sdf.format(c.getTime()));
        }
        return objs;
    }

    /**
     * 当前天数往前加day天还是减day天
     *
     * @param day 加多少天或者减多少天，加的话为正整数，减的话为负数
     * @return
     */
    public static Date addDay(Integer day) {
        Date dateDay = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(dateDay);
        c.add(Calendar.DAY_OF_MONTH, day);// 与开始日期加1
        return c.getTime();
    }

    /**
     * 当前天数往前加多少月还是减多少月
     *
     * @return
     * @parammonth 加多少月或者减多少月，加的话为正整数，减的话为负数
     */
    public static Date addMonth(Integer day) {
        Date dateDay = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(dateDay);
        c.add(Calendar.MONTH, day);// 与开始日期加1月
        return c.getTime();
    }

    /**
     * 当前天数往前加多少年还是减多少年
     *
     * @return
     * @paramyear 加多少年或者减多少年，加的话为正整数，减的话为负数
     */
    public static Date addYear(Integer day) {
        Date dateDay = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(dateDay);
        c.add(Calendar.YEAR, day);// 与开始日期加1年
        return c.getTime();
    }

    public static Date addSecond(int second) {
        Date dateDay = new Date();
        Calendar c = Calendar.getInstance();
        c.setTime(dateDay);
        c.add(Calendar.SECOND, second);// 当前时间加多少秒
        return c.getTime();
    }

    /**
     * 比较两日期类型大小，开始只能小于等于结束的
     *
     * @param start 第一个
     * @param end   第二个
     * @return start <= end
     */
    public static boolean compareDate(String start, String end, String pattern) {
        if (ToolUtil.isEmpty(start) && ToolUtil.isEmpty(end)) {
            return false;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            return compareDate(sdf.parse(start), sdf.parse(end));
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            throw new BusinessException("时间比较出错");
        }
    }

    /**
     * 比较两日期类型大小，开始只能小于等于结束的
     *
     * @param start
     * @param end
     * @return
     */
    public static boolean compareDate(Date start, Date end) {
        if (start.getTime() <= end.getTime()) {
            return true;
        }
        return false;
    }

    /**
     * 获取当前时间返回为字符串格式
     *
     * @param pattern 需要转换成的字符串类型
     * @return
     */
    public static String getDateStr(String pattern) {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(date);
    }

    /**
     * 判断是否小于当前时间
     *
     * @param str 日期类型字符串
     * @return true 小于 false 相反
     */
    public static boolean judgeCurrentDate(String str) {
        Date date = stringToDate(YMD_HMS, str);
        return date.getTime() < new Date().getTime();
    }
}
